#ifndef _H_SHAPES_TRIANGLE
#define _H_SHAPES_TRIANGLE
#include "../core/heads.hpp"
#include "../core/geometry.hpp"
#include "../core/shape.hpp"
#include "../core/interaction.hpp"
namespace chen {


// The transform of triangles is always unit transform.
class Triangle : public Shape {
public:
    Point3 a, b, c;
    Float _area;
    inline Triangle (const Transform * w2o, const Material * mat,
        const Point3 & aa, const Point3 & bb, const Point3 & cc
    ): Shape(&transform_unit, mat), a(w2o->reversed(aa)), b(w2o->reversed(bb)), c(w2o->reversed(cc)) {
        _area = cross(bb-aa, cc-aa).lengthSquared()/2;
        Shape::wbnd = Bound3(
            Point3(
                min(a.x, min(b.x, c.x)),
                min(a.y, min(b.y, c.y)),
                min(a.z, min(b.z, c.z))
            ),
            Point3(
                max(a.x, max(b.x, c.x)),
                max(a.y, max(b.y, c.y)),
                max(a.z, max(b.z, c.z))
            )
        );
        flags = FSHAPE_SUPUSP|FSHAPE_SUPUSPFR;
    }
    bool interact (const Ray & r, SurfInteract * si) const;
    bool mask (const Ray & r) const;
    // Note that the area function returns the area of the untransformed geometry
    inline Float area () const {return _area;}
    void uniformSample (const Point2 & u, Interact * si, Point2 * uv, Float * pdf) const ;
    void uniformSampleFrom (const Point2 & u, const Interact & from, Interact * si, Point2 * uv, Float * pdf) const ;
    inline std::string nameit () const {
        return "Triangle Shape";
    }
};
}
#endif